package com.jrfid.smartcabinet.demo.ui.take_result

import android.app.Application
import android.os.CountDownTimer
import android.view.View
import androidx.databinding.ObservableBoolean
import androidx.databinding.ObservableField
import androidx.lifecycle.LifecycleOwner
import androidx.lifecycle.viewModelScope
import androidx.navigation.NavController
import com.blankj.utilcode.util.LogUtils
import com.blankj.utilcode.util.StringUtils
import com.blankj.utilcode.util.ThreadUtils
import com.blankj.utilcode.util.ToastUtils
import com.jrfid.devicemanager.library.CMDData
import com.jrfid.devicemanager.library.DeviceType
import com.jrfid.devicemanager.library.DevicesManager
import com.jrfid.devicemanager.library.packet.UHFPacketData
import com.jrfid.devicemanager.library.packet.UHFTagInfoModel
import com.jrfid.smartcabinet.demo.R
import com.jrfid.smartcabinet.demo.base.BaseViewModel
import com.jrfid.smartcabinet.demo.model.CabinetConfigInfoModel
import com.jrfid.smartcabinet.demo.model.SocketMsgModel
import com.jrfid.smartcabinet.demo.model.TagInfoModel
import com.jrfid.smartcabinet.demo.ui.take_result.adapter.TakeResultAdapter
import com.jrfid.smartcabinet.demo.ui.taking.TakingFragmentArgs
import com.jrfid.smartcabinet.demo.utils.Config
import com.jrfid.smartcabinet.demo.utils.KTDataUtils
import com.jrfid.smartcabinet.demo.utils.TCPConnectUtils
import com.xuhao.didi.core.iocore.interfaces.ISendable
import com.xuhao.didi.core.pojo.OriginalData
import com.xuhao.didi.socket.client.sdk.client.ConnectionInfo
import com.xuhao.didi.socket.client.sdk.client.action.SocketActionAdapter
import com.xuhao.didi.socket.client.sdk.client.connection.IConnectionManager
import kotlinx.coroutines.*
import java.lang.Exception
import kotlin.experimental.and

class TakeResultViewModel(application: Application, navController: NavController) : BaseViewModel(application, navController) {

    val adapter = TakeResultAdapter()
    var btnText = ObservableField(getString(R.string.btn_confirm))
    var btnEnable = ObservableBoolean(false)

    /**
     * 是否取货模式
     */
    private var isTake = false
    var isTakeMode = ObservableBoolean(false)
    private var tagArray: Array<TagInfoModel> = arrayOf()
    private var tagInfoList = mutableListOf<TagInfoModel>()
    private val cabinetNameMap = hashMapOf<Int, String>()
//    private val managerList = mutableListOf<IConnectionManager>()
//    private val socketListener = object : SocketActionAdapter() {
//        override fun onSocketConnectionSuccess(info: ConnectionInfo, action: String?) {
//            super.onSocketConnectionSuccess(info, action)
//        }
//
//        override fun onSocketConnectionFailed(info: ConnectionInfo, action: String?, e: Exception?) {
//            super.onSocketConnectionFailed(info, action, e)
////            ToastUtils.showShort("${cabinetNameMap[info.ip]}连接失败")
//            LogUtils.dTag(TAG, "${cabinetNameMap[info.ip]}连接失败")
//        }
//
//        override fun onSocketDisconnection(info: ConnectionInfo, action: String?, e: Exception?) {
//            super.onSocketDisconnection(info, action, e)
////            ToastUtils.showShort("${cabinetNameMap[info.ip]}连接断开")
//            LogUtils.dTag(TAG, "${cabinetNameMap[info.ip]}连接断开")
//        }
//
//        override fun onSocketReadResponse(info: ConnectionInfo, action: String, data: OriginalData) {
//            super.onSocketReadResponse(info, action, data)
//            val body = data.bodyBytes
//            val header = data.headBytes
//            LogUtils.dTag(TAG, "${info.ip}收到数据：${KTDataUtils.byteArrayToHex(data.headBytes)} ${KTDataUtils.byteArrayToHex(data.bodyBytes)}")
//            if (header.size == 2 && header[1] > 0x0A) {
//                //读到标签
//                val len = header[1].toInt()
//                val epc = KTDataUtils.byteArrayToHexTrim(body.toList().subList(5, len - 2).toByteArray())
//                if (isTake) {
//                    ThreadUtils.runOnUiThread {
//                        adapter.remove(epc)
//                    }
//                } else {
//                    val temp = tagInfoList.find { it.epc == epc }
//                    if (temp == null) {
//                        val tagInfoModel = TagInfoModel().apply {
//                            this.cabinetName = cabinetNameMap[info.ip] ?: ""
//                            this.epc = epc
//                            this.count = 1
//                        }
//                        ThreadUtils.runOnUiThread {
//                            adapter.addData(tagInfoModel)
//                        }
//                    }
//                }
//            }
//        }
//
//        override fun onSocketWriteResponse(info: ConnectionInfo, action: String?, data: ISendable) {
//            super.onSocketWriteResponse(info, action, data)
//            LogUtils.dTag(TAG, "${info.ip}发送数据：${KTDataUtils.byteArrayToHex(data.parse())}")
//        }
//    }
//    private val countDownTimer = object : CountDownTimer(1000 * 3, 200) {
//        override fun onTick(millisUntilFinished: Long) {
//            btnText.set(getStringFormat(R.string.btn_confirm_format, (millisUntilFinished / 1000).toInt()))
////            if (millisUntilFinished / 1000 <= 20) {
////                //15s后显示确认按钮
////                btnEnable.set(true)
////            } else {
//            managerList.forEach {
//                it.send(SocketMsgModel(CMDData.R2000.realTimeInventory()))
//            }
////            }
//        }
//
//        override fun onFinish() {
//            managerList.forEach {
//                it.unRegisterReceiver(socketListener)
//                it.disconnect()
//            }
//            btnText.set(getString(R.string.btn_confirm))
//            btnEnable.set(true)
////            ThreadUtils.runOnUiThread {
////                navController.navigateUp()
////            }
//        }
//    }

//    private val onReceiveMainBoardDataListener = object : Manager.OnSerialPortDataListener {
//
//        override fun onDataReceived(byteArray: ByteArray) {
//            LogUtils.d("main recv: ${KTDataUtils.byteArrayToHexTrim(byteArray)}")
//            val len = byteArray[1].toInt()
//            val dataLen = len - 3
//            val cmd = byteArray[3]
//            val address = byteArray[2]
//            when (cmd) {
//                CMDData.Cabinet.CMD_UHF_DATA -> {
//                    val uhfData = ByteArray(dataLen)
//                    System.arraycopy(byteArray, 4, uhfData, 0, uhfData.size)
//                    onReceivedUHFData(address, uhfData)
//                }
//            }
//        }
//
//        override fun onDataSend(byteArray: ByteArray) {
//            LogUtils.d("main send: ${KTDataUtils.byteArrayToHexTrim(byteArray)}")
//        }
//
//    }

//    private fun onReceivedUHFData(address: Byte, byteArray: ByteArray) {
//        val len = byteArray[1].toInt()
//        val cmd = byteArray[3]
//        when (cmd) {
//            (0x89).toByte(), (0x8A).toByte(), (0x8B).toByte() -> {
//                //盘存标签
//                if (len < 10) {
//                    //盘存错误
//                    if (address == 0x01.toByte()) {
//                        sendInventoryCMD1()
//                    } else if (address == 0x02.toByte()) {
//                        sendInventoryCMD2()
//                    }
//                } else if (len == 10) {
//                    //盘存结束
//                    if (address == 0x01.toByte()) {
//                        sendInventoryCMD1()
//                    } else if (address == 0x02.toByte()) {
//                        sendInventoryCMD2()
//                    }
//                } else {
//                    //盘存到标签
//                    viewModelScope.launch {
//                        val time = System.currentTimeMillis()
//                        val epcLen = len - 7
//                        val epcData = ByteArray(epcLen)
//                        System.arraycopy(byteArray, 7, epcData, 0, epcLen)
//                        val epc = KTDataUtils.byteArrayToHexTrim(epcData)
//                        if (isTake) {
//                            withContext(Dispatchers.Main) {
//                                adapter.remove(epc)
//                            }
//                        } else {
//                            val temp = tagInfoList.find { it.epc == epc }
//                            if (temp == null) {
//                                val tagInfoModel = TagInfoModel().apply {
//                                    this.cabinetName = cabinetNameMap[address.toInt()] ?: ""
//                                    this.epc = epc
//                                    this.count = 1
//                                }
//                                withContext(Dispatchers.Main) {
//                                    adapter.addData(tagInfoModel)
//                                }
//                            }
//                        }
//                    }
//                }
//            }
//        }
//    }

    private val listener = object : DevicesManager.OnDeviceDataCallback {
        override fun onDataReceived(deviceType: DeviceType, address: Byte, byteArray: ByteArray) {
            if (deviceType == DeviceType.UHF) {
                val model = UHFPacketData(byteArray)
                when (model.cmd) {
                    (0x89).toByte(), (0x8A).toByte(), (0x8B).toByte() -> {
                        //盘存标签
                        if (model.len < 10) {
                            //盘存错误
//                            if (address == 0x01.toByte()) {
//                                sendInventoryCMD1()
//                            } else if (address == 0x02.toByte()) {
//                                sendInventoryCMD2()
//                            }
                        } else if (model.len == 10) {
                            //盘存结束
//                            if (address == 0x01.toByte()) {
//                                sendInventoryCMD1()
//                            } else if (address == 0x02.toByte()) {
//                                sendInventoryCMD2()
//                            }
                        } else {
                            //盘存到标签
                            viewModelScope.launch {
                                val tag = UHFTagInfoModel(model.data)
                                if (isTake) {
                                    withContext(Dispatchers.Main) {
                                        adapter.remove(tag.epc)
                                    }
                                } else {
                                    val temp = tagInfoList.find { it.epc == tag.epc }
                                    if (temp == null) {
                                        val tagInfoModel = TagInfoModel().apply {
                                            this.cabinetName = cabinetNameMap[address.toInt()] ?: ""
                                            this.epc = tag.epc
                                            this.count = 1
                                        }
                                        withContext(Dispatchers.Main) {
                                            adapter.addData(tagInfoModel)
                                        }
                                    }
                                }
                            }

                        }
                    }
                }
            }
        }

        override fun onDataSend(deviceType: DeviceType, address: Byte, byteArray: ByteArray) {

        }

    }

    private var isInventorying = false
    private var retryInventoryJob1
            : Job
    ? = null

    private fun sendInventoryCMD1() {
        retryInventoryJob1?.cancel()
        if (isInventorying) {
            DevicesManager.instance.sendData(
                DeviceType.UHF, 0x01,
                CMDData.R2000.fastSwitchAntInventoryFor8Ant(
                    session = 1,
                    ant4 = false,
                    ant5 = false,
                    ant6 = false,
                    ant7 = false
                )
            )
            retryInventoryJob1 = viewModelScope.launch {
                delay(300)
                sendInventoryCMD1()
            }
        }
    }

    private var retryInventoryJob2
            : Job
    ? = null

    private fun sendInventoryCMD2() {
        retryInventoryJob2?.cancel()
        if (isInventorying) {
            DevicesManager.instance.sendData(
                DeviceType.UHF, 0x02,
                CMDData.R2000.fastSwitchAntInventoryFor8Ant(
                    session = 1,
                    ant7 = false
                )
            )
            retryInventoryJob2 = viewModelScope.launch {
                delay(300)
                sendInventoryCMD2()
            }
        }
    }

    private fun sendLoopInventory1() {
        if (isInventorying) {
            DevicesManager.instance.startInventory(
                5,
                address = 0x01,
                CMDData.R2000.fastSwitchAntInventoryFor8Ant(ant4 = false, ant5 = false, ant6 = false, ant7 = false, session = 1)
            )
        }
    }

    private fun sendLoopInventory2() {
        if (isInventorying) {
            DevicesManager.instance.startInventory(
                5,
                address = 0x02,
                CMDData.R2000.fastSwitchAntInventoryFor8Ant(ant7 = false, session = 1)
            )
        }
    }


    fun setData(isTake: Boolean, tagArray: Array<TagInfoModel>, cabinetArray: Array<CabinetConfigInfoModel>) {
        //根据柜子列表连接读卡器
        cabinetArray.forEach {
//            val manager = TCPConnectUtils.connectRFIDDevice(it.readerIP.get(), it.readerPort.get()?.toIntOrNull(), socketListener)
//            managerList.add(manager)
            cabinetNameMap[it.address.get()!!.toInt()] = it.name.get() ?: ""
        }
        this.isTake = isTake
        isTakeMode.set(isTake)
        this.tagArray = tagArray
        tagInfoList.addAll(tagArray)
        if (isTake) {
            //取货
            adapter.addData(tagArray.toList())
        }
        viewModelScope.launch {
            isInventorying = true
//            sendInventoryCMD1()
//            sendInventoryCMD2()
            sendLoopInventory1()
            sendLoopInventory2()
            for (i in 5 downTo 0) {
                withContext(Dispatchers.Main) {
                    btnText.set(getStringFormat(R.string.btn_confirm_format, i))
                }
                delay(1000)
            }
            isInventorying = false
            withContext(Dispatchers.Main) {
                btnText.set(getString(R.string.btn_confirm))
                btnEnable.set(true)
            }
        }
    }

    override fun onCreate(owner: LifecycleOwner) {
        super.onCreate(owner)
        DevicesManager.instance.addOnDeviceDataListener(listener)
//        MainBoardManager.instance.addOnSerialPortDataListener(onReceiveMainBoardDataListener)
    }

    override fun onDestroy(owner: LifecycleOwner) {
        super.onDestroy(owner)
        DevicesManager.instance.removeOnDeviceDataListener(listener)
//        MainBoardManager.instance.removeOnSerialPortDataListener(onReceiveMainBoardDataListener)
    }

    fun onClickBtnConfirm(view: View) {
//        countDownTimer.cancel()
//        countDownTimer.onFinish()
        ThreadUtils.runOnUiThread {
            navController.navigateUp()
        }
    }
}